home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / _archvrs / unix / lha101u / src / lhext.c < prev    next >
C/C++ Source or Header  |  1992-09-23  |  7KB  |  359 lines

  1. /*----------------------------------------------------------------------*/
  2. /*            LHarc Extract Command                */
  3. /*        This is part of LHarc UNIX Archiver Driver        */
  4. /*                                    */
  5. /*        Copyright(C) MCMLXXXIX  Yooichi.Tagawa            */
  6. /*                                    */
  7. /*  V0.00  Original                1988.05.23  Y.Tagawa    */
  8. /*  V1.00  Fixed                1989.09.22  Y.Tagawa    */
  9. /*  V0.03  LHa for UNIX                1991.12.17  M.Oki    */
  10. /*----------------------------------------------------------------------*/
  11.  
  12. #include "lharc.h"
  13.  
  14. extern int decode_lzhuf ();
  15.  
  16. static boolean
  17. inquire_extract (name)
  18. char *name;
  19. {
  20.   struct stat stbuf;
  21.  
  22.   if (stat (name, &stbuf) >= 0)
  23.     {
  24.       if (!is_regularfile (&stbuf))
  25.     {
  26.       error ("Already exist (not a file)", name);
  27.       return FALSE;
  28.     }
  29.  
  30.       if (noexec)
  31.     {
  32.       printf ("EXTRACT %s but file is exist.\n", name);
  33.       return FALSE;
  34.     }
  35.       else if (!force)
  36.     {
  37.       if (!isatty(0)) return FALSE;
  38.       switch (inquire ("OverWrite ?(Yes/No/All)", name, "YyNnAa"))
  39.         {
  40.         case 0:
  41.         case 1:        /* Y/y */
  42.           break;
  43.         case 2:
  44.         case 3:        /* N/n */
  45.           return FALSE;
  46.         case 4:
  47.         case 5:        /* A/a */
  48.           force = TRUE;
  49.           break;
  50.         }
  51.     }
  52.     }
  53.  
  54.   if (noexec)
  55.     printf ("EXTRACT %s\n", name);
  56.  
  57.   return TRUE;
  58. }
  59.  
  60. static boolean
  61. make_parent_path (name)
  62. char *name;
  63. {
  64.   char path[FILENAME_LENGTH];
  65.   struct stat stbuf;
  66.   register char *p;
  67.  
  68.   /* make parent directory name into PATH for recursive call */
  69.   strcpy (path, name);
  70.   for (p = path + strlen (path); p > path; p--)
  71.     if (p[-1] == '/')
  72.       {
  73.     *--p = '\0';
  74.     break;
  75.       }
  76.  
  77.   if (p == path)
  78.     {
  79.       message ("Why?", "ROOT");
  80.       return FALSE;            /* no more parent. */
  81.     }
  82.  
  83.   if (stat (path, &stbuf) >= 0)
  84.     {
  85.       if (is_directory (&stbuf))
  86.     return TRUE;
  87.       error ("Not a directory", path);
  88.       return FALSE;
  89.     }
  90.   errno = 0;
  91.  
  92.   if (verbose)
  93.     printf ("Making directory \"%s\".", path);
  94.  
  95.   if (mkdir (path, 0777) >= 0)/* try */
  96.     return TRUE;            /* successful done. */
  97.   errno = 0;
  98.  
  99.   if (!make_parent_path (path))
  100.     return FALSE;
  101.  
  102.   if (mkdir (path, 0777) < 0)    /* try again */
  103.     {
  104.       message ("Cannot make directory", path);
  105.       return FALSE;
  106.     }
  107.  
  108.   return TRUE;
  109. }
  110.  
  111. static FILE *
  112. open_with_make_path (name)
  113. char *name;
  114. {
  115.   FILE *fp;
  116.  
  117.   if ((fp = fopen (name, WRITE_BINARY)) == NULL)
  118.     {
  119.       errno = 0;
  120.       if (!make_parent_path (name) ||
  121.       (fp = fopen (name, WRITE_BINARY)) == NULL)
  122.       error ("Cannot extract", name);
  123.       errno = 0;
  124.     }
  125.   return fp;
  126. }
  127.  
  128. static void
  129. adjust_info (name,hdr)
  130. char *name;
  131. LzHeader *hdr;
  132. {
  133.   time_t utimebuf[2];
  134.   unsigned myuid;
  135.  
  136.   /* adjust file stamp */
  137.   utimebuf[0] = utimebuf[1] = hdr->unix_last_modified_stamp;
  138.   utime (name, utimebuf);
  139.  
  140.   if (hdr->extend_type == EXTEND_UNIX
  141.       || hdr->extend_type == EXTEND_OS68K
  142.       || hdr->extend_type == EXTEND_XOSK)
  143.     {
  144. #if 0      /* GRR:  chown(,-1,) is not valid argument */
  145.       if (!myuid)
  146.           chown (name, hdr->unix_uid, hdr->unix_gid);
  147.       else if (myuid == hdr->unix_uid)
  148.           chown (name, -1           , hdr->unix_gid);
  149. #endif
  150.       if ((myuid = getuid()) == hdr->unix_uid  ||  myuid == 0)
  151.           chown (name, hdr->unix_uid, hdr->unix_gid);
  152. #ifdef NOT_COMPATIBLE_MODE
  153.       Please need your modification in this space.
  154. #else
  155.       chmod (name, hdr->unix_mode); /* Do this after chown so suid stays */
  156. #endif
  157.       errno = 0;
  158.     }
  159. }
  160.  
  161. static char *methods[10] =
  162. {
  163.     "-lh0-", "-lh1-", "-lh2-", "-lh3-", "-lh4-",
  164.     "-lh5-", "-lzs-", "-lz5-", "-lz4-", NULL
  165. };
  166.  
  167. static void
  168. extract_one (afp, hdr)
  169. FILE *afp;                    /* archive file */
  170. LzHeader *hdr;
  171. {
  172.   FILE *fp;                    /* output file */
  173.   char name[257];
  174.   int crc;
  175.   int method;
  176.   boolean save_quiet, save_verbose;
  177.   char *q = hdr->name , c;
  178.  
  179.   if ( ignore_directory && rindex(hdr->name,'/') )
  180.     {
  181.       q = (char *)rindex(hdr->name,'/') + 1;
  182.     }
  183.   else
  184.     {
  185.       if ( *q=='/' )
  186.     {
  187.       q++;
  188.       /*
  189.        *    if OSK then strip device name
  190.        */
  191.       if (hdr->extend_type == EXTEND_OS68K
  192.           || hdr->extend_type == EXTEND_XOSK )
  193.         {
  194.           do c=(*q++); while ( c && c!='/' );
  195.           if ( !c || !*q ) q = ".";    /* if device name only */
  196.         }
  197.     }
  198.     }
  199.  
  200.   if (extract_directory)
  201.     sprintf (name, "%s/%s", extract_directory, q);
  202.   else
  203.     strcpy (name, q);
  204.  
  205.   if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
  206.     {
  207.       for (method = 0; ; method++)
  208.     {
  209.       if (methods[method] == NULL)
  210.         {
  211.           error ("Unknown method skiped ...", name);
  212.           return;
  213.         }
  214.       if (bcmp (hdr->method, methods[method], 5) == 0)
  215.         break;
  216.     }
  217.  
  218.       reading_filename = archive_name;
  219.       writting_filename = name;
  220.       if (output_to_stdout || verify_mode)
  221.     {
  222.       if (noexec)
  223.         {
  224.           printf ("%s %s\n", verify_mode ? "VERIFY" : "EXTRACT",name);
  225.           if (afp == stdin)
  226.         {
  227.           int i = hdr->packed_size;
  228.           while(i--) fgetc(afp);
  229.         }
  230.           return;
  231.         }
  232.  
  233.       save_quiet = quiet;
  234.       save_verbose = verbose;
  235.       if (!quiet && output_to_stdout)
  236.         {
  237.           printf ("::::::::\n%s\n::::::::\n", name);
  238.           quiet = TRUE;
  239.           verbose = FALSE;
  240.         }
  241.       else if (verify_mode)
  242.         {
  243.           quiet = FALSE;
  244.           verbose = TRUE;
  245.         }
  246.  
  247.       crc = decode_lzhuf
  248.         (afp, stdout, hdr->original_size, hdr->packed_size, name, method);
  249.       quiet = save_quiet;
  250.       verbose = save_verbose;
  251.     }
  252.       else
  253.     {
  254.       if (!inquire_extract (name))
  255.         return;
  256.  
  257.       if (noexec)
  258.         {
  259.           if (afp == stdin)
  260.         {
  261.           int i = hdr->packed_size;
  262.           while(i--) fgetc(afp);
  263.         }
  264.           return;
  265.         }
  266.  
  267.       signal (SIGINT, interrupt);
  268.       signal (SIGHUP, interrupt);
  269.  
  270.       unlink (name);
  271.       errno = 0;
  272.       remove_extracting_file_when_interrupt = TRUE;
  273.       if ((fp = open_with_make_path (name)) != NULL)
  274.         {
  275.           crc = decode_lzhuf
  276.         (afp, fp, hdr->original_size, hdr->packed_size, name, method);
  277.           fclose (fp);
  278.         }
  279.       remove_extracting_file_when_interrupt = FALSE;
  280.       signal (SIGINT, SIG_DFL);
  281.       signal (SIGHUP, SIG_DFL);
  282.  
  283.       if (!fp)
  284.         return;
  285.     }
  286.  
  287.       errno = 0;
  288.       if (hdr->has_crc && crc != hdr->crc)
  289.     error ("CRC error", name);
  290.  
  291.     }
  292.   else if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY)
  293.     {
  294.       if (!ignore_directory && !verify_mode)
  295.     {
  296.       if (noexec)
  297.         {
  298.           printf ("EXTRACT %s (directory)\n", name);
  299.           return;
  300.         }
  301.       /* NAME has trailing SLASH '/', (^_^) */
  302.       if (!output_to_stdout && !make_parent_path (name))
  303.         return;
  304.     }
  305.     }
  306.   else
  307.     {
  308.       error ("Unknown information", name);
  309.     }
  310.  
  311.   if (!output_to_stdout)
  312.     adjust_info (name,hdr);
  313. }
  314.  
  315.  
  316. /*----------------------------------------------------------------------*/
  317. /*            EXTRACT COMMAND MAIN                */
  318. /*----------------------------------------------------------------------*/
  319.  
  320. void
  321. cmd_extract ()
  322. {
  323.   LzHeader hdr;
  324.   long pos;
  325.   FILE *afp;
  326.  
  327.   /* open archive file */
  328.   if ((afp = open_old_archive ()) == NULL)
  329.     fatal_error (archive_name);
  330.   if (archive_is_msdos_sfx1 (archive_name))
  331.     skip_msdos_sfx1_code (afp);
  332.  
  333.   /* extract each files */
  334.   while (get_header (afp, &hdr))
  335.     {
  336.       if (need_file (hdr.name))
  337.     {
  338.       pos = ftell (afp);
  339.       extract_one (afp, &hdr);
  340.       fseek (afp, pos + hdr.packed_size, SEEK_SET);
  341.     }
  342.       else
  343.     {
  344.       if (afp != stdin)
  345.         fseek (afp, hdr.packed_size, SEEK_CUR);
  346.       else
  347.         {
  348.           int i = hdr.packed_size;
  349.           while(i--) fgetc(afp);
  350.         }
  351.     }
  352.     }
  353.  
  354.   /* close archive file */
  355.   fclose (afp);
  356.  
  357.   return;
  358. }
  359.